# -*- coding: utf-8 -*-
"""
Created on 2020-11-11 07:59:30

@File:    combine_wx_zfb.py
@author: wyf
"""

import os
import sys
import time
import datetime

# #先把pip升级到最新版本
# path = '"'+os.path.dirname(sys.executable)+'\\pip" install --upgrade pip'
# os.system(path)

#导入必要的扩展库
#pandas扩展库
try:
    import pandas as pd
except:
    path = '"'+os.path.dirname(sys.executable)+'\\pip" install pandas'
    os.system(path)
    import pandas as pd

#pandas扩展库
try:
    import openpyxl 
except:
    path = '"'+os.path.dirname(sys.executable)+'\\pip" install openpyxl'
    os.system(path)
    import openpyxl



    

from helper import print_data_info, get_data, update_data_types

"""
基于以下假设，适用于2020年7月以来下载的账单文件：

微信账单中包含的项目为11个：交易时间，交易类型，交易对方，商品，收/支，金额(元)，支付方式，当前状态，交易单号，商户单号，备注
支付宝账单中包含的项目为16个：交易号，商家订单号，交易创建时间，付款时间，最近修改时间，交易来源地，类型，交易对方，商品名称，金额（元），收/支，交易状态，服务费（元），成功退款（元），备注，资金状态

微信账单和支付宝账单前16行和前4行是废掉的，csv文件编码格式分别为utf-8和gbk。

交易时间分别在“交易时间”和“交易创建时间”中。

如官方下载的文档有名称修改，请相应的修改本脚本涉及的字符串常量。

若仍有考虑不周的方面，欢迎提建议改进。

注意，合并后的账单不包含银行卡收入，例如工资、他人的银行卡转账等项目，需自行添加。

"""

def transaction_checking_zfb_wzx(data, column_types=None):
    """
    在支付宝账单中，有些资金状态为“空”或“资金转移”的，将服务费算作支出。
    :param data:
    :return:
    """
    # 对于资金状态为空的情况，是交易关闭，不计入结算。
    data = data.drop(data[data['资金状态'] == ''].index)
    # 对于资金状态为“资金转移”的，如果服务费为零，那么也删除该行。
    data = data.drop(data[(data['资金状态'] == '资金转移') & (data['服务费（元）'] == 0.0)].index)
    # 将服务费算作支出，填写到金额中。
    data.loc[data['服务费（元）'] > 0.0, ['收/支']] = '支出'
    # print(data.loc[data['服务费（元）'] > 0.0, ['交易号']])  # 这些是出手续费的交易号
    # 将手续费金额填写进收支金额中。
    data.loc[data['服务费（元）'] > 0.0, ['金额（元）']] = data.loc[data['服务费（元）'] > 0.0, ['服务费（元）']].values
    # 更新数据格式。
    data = update_data_types(data, column_types)
    return data		# 返回数据

def transaction_checking_zfb_yl(data, column_types=None):
    """
    在支付宝账单中，有些资金状态为“空”或“资金转移”的，将服务费算作支出。
    :param data:
    :return:
    """
    # 对于资金状态为空的情况，是交易关闭，不计入结算。
    data = data.drop(data[data['资金状态'] == ''].index)
    # 对于资金状态为“资金转移”的，如果服务费为零，那么也删除该行。
    data = data.drop(data[(data['资金状态'] == '资金转移') & (data['服务费（元）'] == 0.0)].index)
    # 将服务费算作支出，填写到金额中。
    data.loc[data['服务费（元）'] > 0.0, ['收/支']] = '支出'
    # print(data.loc[data['服务费（元）'] > 0.0, ['交易号']])  # 这些是出手续费的交易号
    # 将手续费金额填写进收支金额中。
    data.loc[data['服务费（元）'] > 0.0, ['金额（元）']] = data.loc[data['服务费（元）'] > 0.0, ['服务费（元）']].values
    # 更新数据格式。
    data = update_data_types(data, column_types)
    return data	#返回数据

def extract_and_rename(data, columns, column_corr):
    """
    从原始表格中提取出数据，并更换为指定的列名。
    :param data:
    :param columns:
    :param column_corr:
    :return:
    """

    assert isinstance(columns, (list, tuple))
    assert isinstance(column_corr, dict)
    data = data.rename(columns=column_corr)
    data = data[list(columns)]
    return data


def merge(path_zfb_wzx, path_zfb_yl, rules_list, save_path, start='2020/6/1 0:0:0', end='2020/7/1 0:0:0'):
    zfb_wzx, zfb_yl, hb, dt = list(zip(*rules_list))

    # data_zfbW = get_data(path_zfbW, start_line=16, encoding='utf-8')
    # data_zfb = get_data(path_zfb, start_line=4, encoding='gbk')
    data_zfb_wzx = get_data(path_zfb_wzx, start_line=4, encoding='gbk') # 读取文件
    data_zfb_yl = get_data(path_zfb_yl, start_line=4, encoding='gbk') # 读取文件

    data_zfb_wzx['DataSoure']='alipayFromWZX' #增加新的列DataSoure
    data_zfb_yl['DataSoure']='alipayFromYL' #增加新的列DataSoure 说明合并后数据的来源是哪一个文件
    
    # 按照设定的规则 去掉不需要统计的数据条目
    data_zfb_wzx = transaction_checking_zfb_wzx(data_zfb_wzx, {k: v for k, v in zip(zfb_wzx, dt)})
    data_zfb_yl = transaction_checking_zfb_yl(data_zfb_yl, {k: v for k, v in zip(zfb_yl, dt)})

    # 替换列名称与数据类型
    data_zfb_wzx = extract_and_rename(data_zfb_wzx, hb, {k: v for k, v in zip(zfb_wzx, hb)})
    data_zfb_yl = extract_and_rename(data_zfb_yl, hb, {k: v for k, v in zip(zfb_yl, hb)})

    # 合并后排序 返回筛选后的数据账单
    data = pd.concat([data_zfb_wzx, data_zfb_yl], axis=0, sort=False)       # 合并
    data = data.sort_values(by='交易时间')              # 按照交易时间排序
    data = data.reset_index(drop = True) #重新添加索引号
    data = data.loc[(data['交易时间'] > start) & (data['交易时间'] < end)]  # 筛选出满足时间要求的记录
    if data.empty == False:
        print_data_info(data, '合并后账单')

        print('\n{}至{}期间数据统计：'.format(start, end))
        # data_analysis(data)
    
        # d_start = datetime.datetime.strptime(start,'%Y-%m-%d %H:%M:%S').strftime('%y%m%d_%H%M%S')
        # d_end = datetime.datetime.strptime(end,'%Y-%m-%d %H:%M:%S').strftime('%y%m%d_%H%M%S')
        d_start = datetime.datetime.strptime(start,'%Y-%m-%d %H:%M:%S').strftime('%y%m%d')
        d_end = datetime.datetime.strptime(end,'%Y-%m-%d %H:%M:%S').strftime('%y%m%d')
        
        save_path =save_path +'\MergeData_'+ d_start +'To'+ d_end +'.xlsx' 
        # save_path = save_path + '\last.xlsx'
        data.to_excel(save_path, encoding='gbk')
        
        print("已生成结果表")
    else:
        pass

#
# def post_process(data):
#     """
#     对合并后的数据做一些后处理。
#     :param data:
#     :return:
#     """
#     return data


def data_analysis(data):
    print('总收入：{:.2f}元。'.format(sum(data.loc[data['收支'] == '收入', ['交易金额']].values)[0]))
    print('总支出：{:.2f}元。'.format(sum(data.loc[data['收支'] == '支出', ['交易金额']].values)[0]))


if __name__ == "__main__":
    path_zfb_wzx = r'E:\GiteeWarseHouse\BeancountSample\code\csv\alipay_wzx.csv'
    path_zfb_yl = r'E:\GiteeWarseHouse\BeancountSample\code\csv\alipay_yl.csv'
    # save_path = r'E:\GiteeWarseHouse\BeancountSample\code\csv\last_all2.xlsx'
    save_path = r'E:\GiteeWarseHouse\BeancountSample\code\csv\last'
    
    #              支付宝wzx        支付宝yl         合并后    数据类型
    rules_list = [['交易创建时间', '交易创建时间', '交易时间', 'datetime64'],
                  ['交易对方', '交易对方',     '交易对方', 'object'],
                  ['商品名称',     '商品名称',     '商品名称', 'object'],
                  ['交易号', '交易号',       '交易单号', 'object'],
                  ['商家订单号', '商家订单号',   '商户单号', 'object'],
                  ['类型', '类型',         '交易类型', 'object'],
                  ['资金状态', '资金状态',     '当前状态', 'object'],
                  ['收/支',    '收/支',        '收支',     'object'],
                  ['金额（元）', '金额（元）',   '交易金额', 'float64'],
                  ['备注',     '备注',         '备注',     'object'],
                  ['DataSoure','DataSoure','数据来源','object'],
                  ]
 
    month_now = datetime.datetime.now().month
    year_now = datetime.datetime.now().year
    for y in range(2011,2021):
        if y < year_now:
            for i in range(1,13):
                date_start = datetime.datetime(year=y, month=i, day=1, hour=0,minute=0,second=0,microsecond=0)
                if i<12:
                    date_end = date_start.replace(month= i+1)
                else:
                    date_end = date_start.replace(year=y+1,month=1)
               
                str_start = str(date_start)[:19]
                str_end = str(date_end)[:19]

                merge(path_zfb_wzx, path_zfb_yl, rules_list, save_path,
                    start=str_start, end=str_end)


        else:
            for i in range(1,13):
                if i > month_now:
                    break
                else:
                    date_start = datetime.datetime(year=2020, month=i, day=1, hour=0,minute=0,second=0,microsecond=0)
                    date_end = date_start.replace(month= i+1 )
                    
                    str_start = str(date_start)[:19]
                    str_end = str(date_end)[:19]

                    merge(path_zfb_wzx, path_zfb_yl, rules_list, save_path,
                        start=str_start, end=str_end)

